
class CarryTask implements ICreepTask {
  public run(creep: Creep): void {
    // 判断 tower 是否需要补充能量
    let towerTarget:StructureTower | undefined = undefined;
    const myTowers = creep.room.find(FIND_MY_STRUCTURES, { filter: { structureType: STRUCTURE_TOWER }}) as StructureTower[];
      for (const tower of myTowers){
        if (tower.store.getUsedCapacity(RESOURCE_ENERGY) < tower.store.getCapacity(RESOURCE_ENERGY) * 0.9) {
          // 如果能量少于90%，执行某些操作
          towerTarget = tower;
      }
    }
    // 判断 link 是否需要补充能量
    let linkTarget:StructureLink|undefined = undefined;
    const storageLinks = creep.room.storage?.pos.findInRange(FIND_STRUCTURES,1)
      .filter((structure)=> structure.structureType === STRUCTURE_LINK);
    if(storageLinks && storageLinks.length > 0){
      const link = storageLinks[0] as StructureLink;
      if(link && link.store.getFreeCapacity(RESOURCE_ENERGY) > 0){
        linkTarget = link;
      }
      else{
        if(link.cooldown === 0){
          // 发射到控制器link
          if(!creep.room.memory.linkRelation){
            creep.room.memory.linkRelation = {};
          }
          let controllerLinkId = creep.room.memory.linkRelation[link.id];
          if(!controllerLinkId){
            let controllerLinks = creep.room.controller?.pos.findInRange(FIND_STRUCTURES,1)
              .filter((structure)=> structure.structureType === STRUCTURE_LINK) as StructureLink[];
            if(controllerLinks && controllerLinks.length > 0){
              creep.room.memory.linkRelation[link.id] = controllerLinks[0].id;
              controllerLinkId = controllerLinks[0].id;
            }
          }
          if(controllerLinkId){
            const controllerLink = Game.getObjectById(controllerLinkId);
            if(controllerLink && ((controllerLink.store.getCapacity(RESOURCE_ENERGY) - controllerLink.store.getFreeCapacity(RESOURCE_ENERGY)) / controllerLink.store.getCapacity(RESOURCE_ENERGY)) < 0.3){
              link.transferEnergy(controllerLink);
            }
          }
        }
      }
    }


    if(towerTarget){
      if(!creep.memory.working){
        const result = creep.transfer(towerTarget, RESOURCE_ENERGY);
        if (result === ERR_NOT_IN_RANGE) {
          creep.go(towerTarget);
        }
        else if(result === ERR_NOT_ENOUGH_RESOURCES){
          if(creep.room.storage && !creep.memory.working){
            let withdrawResult = creep.withdraw(creep.room.storage, RESOURCE_ENERGY);
            if(withdrawResult === ERR_NOT_IN_RANGE){
              creep.go(creep.room.storage);
            }
            else if(withdrawResult === ERR_NOT_ENOUGH_RESOURCES){
              this.getSource(creep);
            }
          }
        }
      }
      else {
        this.getSource(creep);
      }
    }
    else if(linkTarget) {
      if(!creep.memory.working){
        const result = creep.transfer(linkTarget, RESOURCE_ENERGY);
        if (result === ERR_NOT_IN_RANGE) {
          creep.go(linkTarget);
        }
        else if(result === ERR_NOT_ENOUGH_RESOURCES){
          if(creep.room.storage){
            let withdrawResult = creep.withdraw(creep.room.storage, RESOURCE_ENERGY);
            if(withdrawResult === ERR_NOT_IN_RANGE){
              creep.go(creep.room.storage);
            }
            else if(withdrawResult === ERR_NOT_ENOUGH_RESOURCES){
              this.getSource(creep);
            }
          }
        }
      }
      else {
        this.getSource(creep);
      }
    }
    else{
      if (creep.store.getFreeCapacity() > 0){
        this.getSource(creep);
      }
      else {
        if(creep.room.storage){
          if (creep.transfer(creep.room.storage, RESOURCE_ENERGY) === ERR_NOT_IN_RANGE) {
            creep.go(creep.room.storage);
          }
        }
      }
    }
  }

  private findContainerWithMostEnergyNearSource(room:Room):StructureContainer | null {
    const sources = room.find(FIND_SOURCES);
    let container:StructureContainer | null = null;
    let maxEnergy = 0;
    sources.forEach(source => {
      // 查找距离 Source 最近的容器
      var containers = source.pos.findInRange(FIND_STRUCTURES, 1, {
        filter: (structure) => {
            return (structure.structureType == STRUCTURE_CONTAINER);
        }
      }) as StructureContainer[];
      containers.forEach(containerItem => {
        const energy = containerItem.store.getUsedCapacity(RESOURCE_ENERGY);
        if (energy > maxEnergy) {
          maxEnergy = energy;
          container = containerItem;
        }
      });
    });
    return container;
  }

  private getSource(creep:Creep){
    creep.memory.working = true;
    // 优先拿容器的来进行储存
    let containerTarget:StructureContainer | null = null;
    if(!creep.memory.containerTarget){
      let container = this.findContainerWithMostEnergyNearSource(creep.room);
      if(container){
        creep.memory.containerTarget = container.id;
      }
    }
    else {
      containerTarget = Game.getObjectById(creep.memory.containerTarget);
      if(!containerTarget){
        delete creep.memory.containerTarget;
      }
      if (containerTarget && containerTarget.store.getUsedCapacity(RESOURCE_ENERGY) < (containerTarget.store.getCapacity(RESOURCE_ENERGY) * 0.5)) {
        containerTarget = null;
        delete creep.memory.containerTarget;
      }
    }
    if(containerTarget && containerTarget.store.getUsedCapacity(RESOURCE_ENERGY) > 0){
      // 拿容器的资源
      let result = creep.withdraw(containerTarget, RESOURCE_ENERGY);
      if(result === ERR_NOT_IN_RANGE) {
        creep.go(containerTarget);
      }
    }
    else {
      // 捡地上的资源
      const droppedResources = creep.room.find(FIND_DROPPED_RESOURCES);
      if (droppedResources.length > 0){
        const target = droppedResources[0];
        if (creep.pickup(target) === ERR_NOT_IN_RANGE) {
          creep.go(target);
        }
      }
    }
    if(creep.store.getFreeCapacity() === 0){
      creep.memory.working = false;
    } 
  }
}

export { CarryTask };